#include "teapot_mesh.hpp"
#include "iterator.hpp"

#include <array>
#include <memory>

using namespace generator;

static const gml::dvec3 teapotData[32][4][4] = {
	{{{1.40, 0.00, 2.40}, {1.40, -0.78, 2.40}, {0.78, -1.40, 2.40}, {0.00, -1.40, 2.40}},
	 {{1.34, 0.00, 2.53}, {1.34, -0.75, 2.53}, {0.75, -1.34, 2.53}, {0.00, -1.34, 2.53}},
	 {{1.44, 0.00, 2.53}, {1.44, -0.81, 2.53}, {0.81, -1.44, 2.53}, {0.00, -1.44, 2.53}},
	 {{1.50, 0.00, 2.40}, {1.50, -0.84, 2.40}, {0.84, -1.50, 2.40}, {0.00, -1.50, 2.40}}},
	{{{0.00, -1.40, 2.40}, {-0.78, -1.40, 2.40}, {-1.40, -0.78, 2.40}, {-1.40, 0.00, 2.40}},
	 {{0.00, -1.34, 2.53}, {-0.75, -1.34, 2.53}, {-1.34, -0.75, 2.53}, {-1.34, 0.00, 2.53}},
	 {{0.00, -1.44, 2.53}, {-0.81, -1.44, 2.53}, {-1.44, -0.81, 2.53}, {-1.44, 0.00, 2.53}},
	 {{0.00, -1.50, 2.40}, {-0.84, -1.50, 2.40}, {-1.50, -0.84, 2.40}, {-1.50, 0.00, 2.40}}},
	{{{-1.40, 0.00, 2.40}, {-1.40, 0.78, 2.40}, {-0.78, 1.40, 2.40}, {0.00, 1.40, 2.40}},
	 {{-1.34, 0.00, 2.53}, {-1.34, 0.75, 2.53}, {-0.75, 1.34, 2.53}, {0.00, 1.34, 2.53}},
	 {{-1.44, 0.00, 2.53}, {-1.44, 0.81, 2.53}, {-0.81, 1.44, 2.53}, {0.00, 1.44, 2.53}},
	 {{-1.50, 0.00, 2.40}, {-1.50, 0.84, 2.40}, {-0.84, 1.50, 2.40}, {0.00, 1.50, 2.40}}},
	{{{0.00, 1.40, 2.40}, {0.78, 1.40, 2.40}, {1.40, 0.78, 2.40}, {1.40, 0.00, 2.40}},
	 {{0.00, 1.34, 2.53}, {0.75, 1.34, 2.53}, {1.34, 0.75, 2.53}, {1.34, 0.00, 2.53}},
	 {{0.00, 1.44, 2.53}, {0.81, 1.44, 2.53}, {1.44, 0.81, 2.53}, {1.44, 0.00, 2.53}},
	 {{0.00, 1.50, 2.40}, {0.84, 1.50, 2.40}, {1.50, 0.84, 2.40}, {1.50, 0.00, 2.40}}},
	{{{1.50, 0.00, 2.40}, {1.50, -0.84, 2.40}, {0.84, -1.50, 2.40}, {0.00, -1.50, 2.40}},
	 {{1.75, 0.00, 1.88}, {1.75, -0.98, 1.88}, {0.98, -1.75, 1.88}, {0.00, -1.75, 1.88}},
	 {{2.00, 0.00, 1.35}, {2.00, -1.12, 1.35}, {1.12, -2.00, 1.35}, {0.00, -2.00, 1.35}},
	 {{2.00, 0.00, 0.90}, {2.00, -1.12, 0.90}, {1.12, -2.00, 0.90}, {0.00, -2.00, 0.90}}},
	{{{0.00, -1.50, 2.40}, {-0.84, -1.50, 2.40}, {-1.50, -0.84, 2.40}, {-1.50, 0.00, 2.40}},
	 {{0.00, -1.75, 1.88}, {-0.98, -1.75, 1.88}, {-1.75, -0.98, 1.88}, {-1.75, 0.00, 1.88}},
	 {{0.00, -2.00, 1.35}, {-1.12, -2.00, 1.35}, {-2.00, -1.12, 1.35}, {-2.00, 0.00, 1.35}},
	 {{0.00, -2.00, 0.90}, {-1.12, -2.00, 0.90}, {-2.00, -1.12, 0.90}, {-2.00, 0.00, 0.90}}},
	{{{-1.50, 0.00, 2.40}, {-1.50, 0.84, 2.40}, {-0.84, 1.50, 2.40}, {0.00, 1.50, 2.40}},
	 {{-1.75, 0.00, 1.88}, {-1.75, 0.98, 1.88}, {-0.98, 1.75, 1.88}, {0.00, 1.75, 1.88}},
	 {{-2.00, 0.00, 1.35}, {-2.00, 1.12, 1.35}, {-1.12, 2.00, 1.35}, {0.00, 2.00, 1.35}},
	 {{-2.00, 0.00, 0.90}, {-2.00, 1.12, 0.90}, {-1.12, 2.00, 0.90}, {0.00, 2.00, 0.90}}},
	{{{0.00, 1.50, 2.40}, {0.84, 1.50, 2.40}, {1.50, 0.84, 2.40}, {1.50, 0.00, 2.40}},
	 {{0.00, 1.75, 1.88}, {0.98, 1.75, 1.88}, {1.75, 0.98, 1.88}, {1.75, 0.00, 1.88}},
	 {{0.00, 2.00, 1.35}, {1.12, 2.00, 1.35}, {2.00, 1.12, 1.35}, {2.00, 0.00, 1.35}},
	 {{0.00, 2.00, 0.90}, {1.12, 2.00, 0.90}, {2.00, 1.12, 0.90}, {2.00, 0.00, 0.90}}},
	{{{2.00, 0.00, 0.90}, {2.00, -1.12, 0.90}, {1.12, -2.00, 0.90}, {0.00, -2.00, 0.90}},
	 {{2.00, 0.00, 0.45}, {2.00, -1.12, 0.45}, {1.12, -2.00, 0.45}, {0.00, -2.00, 0.45}},
	 {{1.50, 0.00, 0.23}, {1.50, -0.84, 0.23}, {0.84, -1.50, 0.23}, {0.00, -1.50, 0.23}},
	 {{1.50, 0.00, 0.15}, {1.50, -0.84, 0.15}, {0.84, -1.50, 0.15}, {0.00, -1.50, 0.15}}},
	{{{0.00, -2.00, 0.90}, {-1.12, -2.00, 0.90}, {-2.00, -1.12, 0.90}, {-2.00, 0.00, 0.90}},
	 {{0.00, -2.00, 0.45}, {-1.12, -2.00, 0.45}, {-2.00, -1.12, 0.45}, {-2.00, 0.00, 0.45}},
	 {{0.00, -1.50, 0.23}, {-0.84, -1.50, 0.23}, {-1.50, -0.84, 0.23}, {-1.50, 0.00, 0.23}},
	 {{0.00, -1.50, 0.15}, {-0.84, -1.50, 0.15}, {-1.50, -0.84, 0.15}, {-1.50, 0.00, 0.15}}},
	{{{-2.00, 0.00, 0.90}, {-2.00, 1.12, 0.90}, {-1.12, 2.00, 0.90}, {0.00, 2.00, 0.90}},
	 {{-2.00, 0.00, 0.45}, {-2.00, 1.12, 0.45}, {-1.12, 2.00, 0.45}, {0.00, 2.00, 0.45}},
	 {{-1.50, 0.00, 0.23}, {-1.50, 0.84, 0.23}, {-0.84, 1.50, 0.23}, {0.00, 1.50, 0.23}},
	 {{-1.50, 0.00, 0.15}, {-1.50, 0.84, 0.15}, {-0.84, 1.50, 0.15}, {0.00, 1.50, 0.15}}},
	{{{0.00, 2.00, 0.90}, {1.12, 2.00, 0.90}, {2.00, 1.12, 0.90}, {2.00, 0.00, 0.90}},
	 {{0.00, 2.00, 0.45}, {1.12, 2.00, 0.45}, {2.00, 1.12, 0.45}, {2.00, 0.00, 0.45}},
	 {{0.00, 1.50, 0.23}, {0.84, 1.50, 0.23}, {1.50, 0.84, 0.23}, {1.50, 0.00, 0.23}},
	 {{0.00, 1.50, 0.15}, {0.84, 1.50, 0.15}, {1.50, 0.84, 0.15}, {1.50, 0.00, 0.15}}},
	{{{-1.60, 0.00, 2.03}, {-1.60, -0.30, 2.03}, {-1.50, -0.30, 2.25}, {-1.50, 0.00, 2.25}},
	 {{-2.30, 0.00, 2.03}, {-2.30, -0.30, 2.03}, {-2.50, -0.30, 2.25}, {-2.50, 0.00, 2.25}},
	 {{-2.70, 0.00, 2.03}, {-2.70, -0.30, 2.03}, {-3.00, -0.30, 2.25}, {-3.00, 0.00, 2.25}},
	 {{-2.70, 0.00, 1.80}, {-2.70, -0.30, 1.80}, {-3.00, -0.30, 1.80}, {-3.00, 0.00, 1.80}}},
	{{{-1.50, 0.00, 2.25}, {-1.50, 0.30, 2.25}, {-1.60, 0.30, 2.03}, {-1.60, 0.00, 2.03}},
	 {{-2.50, 0.00, 2.25}, {-2.50, 0.30, 2.25}, {-2.30, 0.30, 2.03}, {-2.30, 0.00, 2.03}},
	 {{-3.00, 0.00, 2.25}, {-3.00, 0.30, 2.25}, {-2.70, 0.30, 2.03}, {-2.70, 0.00, 2.03}},
	 {{-3.00, 0.00, 1.80}, {-3.00, 0.30, 1.80}, {-2.70, 0.30, 1.80}, {-2.70, 0.00, 1.80}}},
	{{{-2.70, 0.00, 1.80}, {-2.70, -0.30, 1.80}, {-3.00, -0.30, 1.80}, {-3.00, 0.00, 1.80}},
	 {{-2.70, 0.00, 1.58}, {-2.70, -0.30, 1.58}, {-3.00, -0.30, 1.35}, {-3.00, 0.00, 1.35}},
	 {{-2.50, 0.00, 1.13}, {-2.50, -0.30, 1.13}, {-2.65, -0.30, 0.94}, {-2.65, 0.00, 0.94}},
	 {{-2.00, 0.00, 0.90}, {-2.00, -0.30, 0.90}, {-1.90, -0.30, 0.60}, {-1.90, 0.00, 0.60}}},
	{{{-3.00, 0.00, 1.80}, {-3.00, 0.30, 1.80}, {-2.70, 0.30, 1.80}, {-2.70, 0.00, 1.80}},
	 {{-3.00, 0.00, 1.35}, {-3.00, 0.30, 1.35}, {-2.70, 0.30, 1.58}, {-2.70, 0.00, 1.58}},
	 {{-2.65, 0.00, 0.94}, {-2.65, 0.30, 0.94}, {-2.50, 0.30, 1.13}, {-2.50, 0.00, 1.13}},
	 {{-1.90, 0.00, 0.60}, {-1.90, 0.30, 0.60}, {-2.00, 0.30, 0.90}, {-2.00, 0.00, 0.90}}},
	{{{1.70, 0.00, 1.43}, {1.70, -0.66, 1.43}, {1.70, -0.66, 0.60}, {1.70, 0.00, 0.60}},
	 {{2.60, 0.00, 1.43}, {2.60, -0.66, 1.43}, {3.10, -0.66, 0.83}, {3.10, 0.00, 0.83}},
	 {{2.30, 0.00, 2.10}, {2.30, -0.25, 2.10}, {2.40, -0.25, 2.03}, {2.40, 0.00, 2.03}},
	 {{2.70, 0.00, 2.40}, {2.70, -0.25, 2.40}, {3.30, -0.25, 2.40}, {3.30, 0.00, 2.40}}},
	{{{1.70, 0.00, 0.60}, {1.70, 0.66, 0.60}, {1.70, 0.66, 1.43}, {1.70, 0.00, 1.43}},
	 {{3.10, 0.00, 0.83}, {3.10, 0.66, 0.83}, {2.60, 0.66, 1.43}, {2.60, 0.00, 1.43}},
	 {{2.40, 0.00, 2.03}, {2.40, 0.25, 2.03}, {2.30, 0.25, 2.10}, {2.30, 0.00, 2.10}},
	 {{3.30, 0.00, 2.40}, {3.30, 0.25, 2.40}, {2.70, 0.25, 2.40}, {2.70, 0.00, 2.40}}},
	{{{2.70, 0.00, 2.40}, {2.70, -0.25, 2.40}, {3.30, -0.25, 2.40}, {3.30, 0.00, 2.40}},
	 {{2.80, 0.00, 2.48}, {2.80, -0.25, 2.48}, {3.53, -0.25, 2.49}, {3.53, 0.00, 2.49}},
	 {{2.90, 0.00, 2.48}, {2.90, -0.15, 2.48}, {3.45, -0.15, 2.51}, {3.45, 0.00, 2.51}},
	 {{2.80, 0.00, 2.40}, {2.80, -0.15, 2.40}, {3.20, -0.15, 2.40}, {3.20, 0.00, 2.40}}},
	{{{3.30, 0.00, 2.40}, {3.30, 0.25, 2.40}, {2.70, 0.25, 2.40}, {2.70, 0.00, 2.40}},
	 {{3.53, 0.00, 2.49}, {3.53, 0.25, 2.49}, {2.80, 0.25, 2.48}, {2.80, 0.00, 2.48}},
	 {{3.45, 0.00, 2.51}, {3.45, 0.15, 2.51}, {2.90, 0.15, 2.48}, {2.90, 0.00, 2.48}},
	 {{3.20, 0.00, 2.40}, {3.20, 0.15, 2.40}, {2.80, 0.15, 2.40}, {2.80, 0.00, 2.40}}},
	{{{0.00, 0.00, 3.15}, {0.00, 0.00, 3.15}, {0.00, 0.00, 3.15}, {0.00, 0.00, 3.15}},
	 {{0.80, 0.00, 3.15}, {0.80, -0.45, 3.15}, {0.45, -0.80, 3.15}, {0.00, -0.80, 3.15}},
	 {{0.00, 0.00, 2.85}, {0.00, 0.00, 2.85}, {0.00, 0.00, 2.85}, {0.00, 0.00, 2.85}},
	 {{0.20, 0.00, 2.70}, {0.20, -0.11, 2.70}, {0.11, -0.20, 2.70}, {0.00, -0.20, 2.70}}},
	{{{0.00, 0.00, 3.15}, {0.00, 0.00, 3.15}, {0.00, 0.00, 3.15}, {0.00, 0.00, 3.15}},
	 {{0.00, -0.80, 3.15}, {-0.45, -0.80, 3.15}, {-0.80, -0.45, 3.15}, {-0.80, 0.00, 3.15}},
	 {{0.00, 0.00, 2.85}, {0.00, 0.00, 2.85}, {0.00, 0.00, 2.85}, {0.00, 0.00, 2.85}},
	 {{0.00, -0.20, 2.70}, {-0.11, -0.20, 2.70}, {-0.20, -0.11, 2.70}, {-0.20, 0.00, 2.70}}},
	{{{0.00, 0.00, 3.15}, {0.00, 0.00, 3.15}, {0.00, 0.00, 3.15}, {0.00, 0.00, 3.15}},
	 {{-0.80, 0.00, 3.15}, {-0.80, 0.45, 3.15}, {-0.45, 0.80, 3.15}, {0.00, 0.80, 3.15}},
	 {{0.00, 0.00, 2.85}, {0.00, 0.00, 2.85}, {0.00, 0.00, 2.85}, {0.00, 0.00, 2.85}},
	 {{-0.20, 0.00, 2.70}, {-0.20, 0.11, 2.70}, {-0.11, 0.20, 2.70}, {0.00, 0.20, 2.70}}},
	{{{0.00, 0.00, 3.15}, {0.00, 0.00, 3.15}, {0.00, 0.00, 3.15}, {0.00, 0.00, 3.15}},
	 {{0.00, 0.80, 3.15}, {0.45, 0.80, 3.15}, {0.80, 0.45, 3.15}, {0.80, 0.00, 3.15}},
	 {{0.00, 0.00, 2.85}, {0.00, 0.00, 2.85}, {0.00, 0.00, 2.85}, {0.00, 0.00, 2.85}},
	 {{0.00, 0.20, 2.70}, {0.11, 0.20, 2.70}, {0.20, 0.11, 2.70}, {0.20, 0.00, 2.70}}},
	{{{0.20, 0.00, 2.70}, {0.20, -0.11, 2.70}, {0.11, -0.20, 2.70}, {0.00, -0.20, 2.70}},
	 {{0.40, 0.00, 2.55}, {0.40, -0.22, 2.55}, {0.22, -0.40, 2.55}, {0.00, -0.40, 2.55}},
	 {{1.30, 0.00, 2.55}, {1.30, -0.73, 2.55}, {0.73, -1.30, 2.55}, {0.00, -1.30, 2.55}},
	 {{1.30, 0.00, 2.40}, {1.30, -0.73, 2.40}, {0.73, -1.30, 2.40}, {0.00, -1.30, 2.40}}},
	{{{0.00, -0.20, 2.70}, {-0.11, -0.20, 2.70}, {-0.20, -0.11, 2.70}, {-0.20, 0.00, 2.70}},
	 {{0.00, -0.40, 2.55}, {-0.22, -0.40, 2.55}, {-0.40, -0.22, 2.55}, {-0.40, 0.00, 2.55}},
	 {{0.00, -1.30, 2.55}, {-0.73, -1.30, 2.55}, {-1.30, -0.73, 2.55}, {-1.30, 0.00, 2.55}},
	 {{0.00, -1.30, 2.40}, {-0.73, -1.30, 2.40}, {-1.30, -0.73, 2.40}, {-1.30, 0.00, 2.40}}},
	{{{-0.20, 0.00, 2.70}, {-0.20, 0.11, 2.70}, {-0.11, 0.20, 2.70}, {0.00, 0.20, 2.70}},
	 {{-0.40, 0.00, 2.55}, {-0.40, 0.22, 2.55}, {-0.22, 0.40, 2.55}, {0.00, 0.40, 2.55}},
	 {{-1.30, 0.00, 2.55}, {-1.30, 0.73, 2.55}, {-0.73, 1.30, 2.55}, {0.00, 1.30, 2.55}},
	 {{-1.30, 0.00, 2.40}, {-1.30, 0.73, 2.40}, {-0.73, 1.30, 2.40}, {0.00, 1.30, 2.40}}},
	{{{0.00, 0.20, 2.70}, {0.11, 0.20, 2.70}, {0.20, 0.11, 2.70}, {0.20, 0.00, 2.70}},
	 {{0.00, 0.40, 2.55}, {0.22, 0.40, 2.55}, {0.40, 0.22, 2.55}, {0.40, 0.00, 2.55}},
	 {{0.00, 1.30, 2.55}, {0.73, 1.30, 2.55}, {1.30, 0.73, 2.55}, {1.30, 0.00, 2.55}},
	 {{0.00, 1.30, 2.40}, {0.73, 1.30, 2.40}, {1.30, 0.73, 2.40}, {1.30, 0.00, 2.40}}},
	{{{0.00, 0.00, 0.00}, {0.00, 0.00, 0.00}, {0.00, 0.00, 0.00}, {0.00, 0.00, 0.00}},
	 {{1.43, 0.00, 0.00}, {1.43, 0.80, 0.00}, {0.80, 1.43, 0.00}, {0.00, 1.43, 0.00}},
	 {{1.50, 0.00, 0.08}, {1.50, 0.84, 0.08}, {0.84, 1.50, 0.08}, {0.00, 1.50, 0.08}},
	 {{1.50, 0.00, 0.15}, {1.50, 0.84, 0.15}, {0.84, 1.50, 0.15}, {0.00, 1.50, 0.15}}},
	{{{0.00, 0.00, 0.00}, {0.00, 0.00, 0.00}, {0.00, 0.00, 0.00}, {0.00, 0.00, 0.00}},
	 {{0.00, 1.43, 0.00}, {-0.80, 1.43, 0.00}, {-1.43, 0.80, 0.00}, {-1.43, 0.00, 0.00}},
	 {{0.00, 1.50, 0.08}, {-0.84, 1.50, 0.08}, {-1.50, 0.84, 0.08}, {-1.50, 0.00, 0.08}},
	 {{0.00, 1.50, 0.15}, {-0.84, 1.50, 0.15}, {-1.50, 0.84, 0.15}, {-1.50, 0.00, 0.15}}},
	{{{0.00, 0.00, 0.00}, {0.00, 0.00, 0.00}, {0.00, 0.00, 0.00}, {0.00, 0.00, 0.00}},
	 {{-1.43, 0.00, 0.00}, {-1.43, -0.80, 0.00}, {-0.80, -1.43, 0.00}, {0.00, -1.43, 0.00}},
	 {{-1.50, 0.00, 0.08}, {-1.50, -0.84, 0.08}, {-0.84, -1.50, 0.08}, {0.00, -1.50, 0.08}},
	 {{-1.50, 0.00, 0.15}, {-1.50, -0.84, 0.15}, {-0.84, -1.50, 0.15}, {0.00, -1.50, 0.15}}},
	{{{0.00, 0.00, 0.00}, {0.00, 0.00, 0.00}, {0.00, 0.00, 0.00}, {0.00, 0.00, 0.00}},
	 {{0.00, -1.43, 0.00}, {0.80, -1.43, 0.00}, {1.43, -0.80, 0.00}, {1.43, 0.00, 0.00}},
	 {{0.00, -1.50, 0.08}, {0.84, -1.50, 0.08}, {1.50, -0.84, 0.08}, {1.50, 0.00, 0.08}},
	 {{0.00, -1.50, 0.15}, {0.84, -1.50, 0.15}, {1.50, -0.84, 0.15}, {1.50, 0.00, 0.15}}}};

teapot_mesh_t::triangles_t::triangles_t(const teapot_mesh_t& mesh) noexcept
	: mesh_t{&mesh}
	, index_{0}
	, patch_mesh_{std::make_shared<bezier_mesh_t<4, 4>>(teapotData[0],
														gml::ivec2{mesh.segments_, mesh.segments_})}
	, triangles_{patch_mesh_->triangles()}
{
}

bool teapot_mesh_t::triangles_t::done() const noexcept
{
	return index_ == 32;
}

triangle_t teapot_mesh_t::triangles_t::generate() const
{
	if(done())
		throw std::out_of_range("Done!");

	triangle_t triangle = triangles_.generate();

	const int base = index_ * mesh_t->patch_vertex_count_;

	triangle.vertices[0] += base;
	triangle.vertices[1] += base;
	triangle.vertices[2] += base;

	return triangle;
}

void teapot_mesh_t::triangles_t::next()
{
	if(done())
		throw std::out_of_range("Done!");

	triangles_.next();

	if(triangles_.done())
	{
		++index_;

		if(!done())
		{
			patch_mesh_ = std::make_shared<bezier_mesh_t<4, 4>>(
				teapotData[index_], gml::ivec2{mesh_t->segments_, mesh_t->segments_});

			triangles_ = patch_mesh_->triangles();
		}
	}
}

teapot_mesh_t::vertices_t::vertices_t(const teapot_mesh_t& mesh) noexcept
	: mesh_{&mesh}
	, index_{0}
	, patch_mesh_{std::make_shared<bezier_mesh_t<4, 4>>(teapotData[0],
														gml::ivec2{mesh.segments_, mesh.segments_})}
	, vertices_{patch_mesh_->vertices()}
{
}

bool teapot_mesh_t::vertices_t::done() const noexcept
{
	return index_ == 32;
}

mesh_vertex_t teapot_mesh_t::vertices_t::generate() const
{
	return vertices_.generate();
}

void teapot_mesh_t::vertices_t::next()
{
	vertices_.next();

	if(vertices_.done())
	{
		++index_;

		if(!done())
		{
			patch_mesh_ = std::make_shared<bezier_mesh_t<4, 4>>(
				teapotData[index_], gml::ivec2{mesh_->segments_, mesh_->segments_});

			vertices_ = patch_mesh_->vertices();
		}
	}
}

teapot_mesh_t::teapot_mesh_t(int segments) noexcept
	: segments_{segments}
	, patch_vertex_count_{count(bezier_mesh_t<4, 4>{teapotData[0], {segments, segments}}.vertices())}
{
}

teapot_mesh_t::triangles_t teapot_mesh_t::triangles() const noexcept
{
	return triangles_t{*this};
}

teapot_mesh_t::vertices_t teapot_mesh_t::vertices() const noexcept
{
	return vertices_t{*this};
}
